home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / hack / 3_1_3 / sys / amiga / wbcli.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-20  |  40.5 KB  |  2,107 lines

  1. /*    SCCS Id: @(#)wbcli.c  2.1   93/01/08              */
  2. /*    Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1991      */
  3. /*    Copyright (c) Gregg Wonderly, Naperville, IL, 1992, 1993    */
  4. /* NetHack may be freely redistributed.  See license for details. */
  5.  
  6. /* Friendly Intuition interface for NetHack 3.1 on the Amiga */
  7.  
  8. /*
  9.  * This file contains many routines common to the CLI and WB interfaces,
  10.  * along with a few specific to each.  #defining CLI supports the CLI
  11.  * interface; not #defining it supports (along with wb.c) the WB interface.
  12.  */
  13.  
  14. /*#include "Incl:date.h"          /* this gives us the version string */
  15. #include "Incl:patchlevel.h"    /* and the individual bits */
  16.  
  17. #ifdef AZTEC_C
  18. /* Aztec doesn't recognize __chip syntax */
  19. # define __chip
  20. #endif
  21.  
  22. #include "Amiga:wbdefs.h"       /* Miscellany information */
  23. #ifdef  INTUI_NEW_LOOK
  24. #define NewWindow   ExtNewWindow
  25. #define NewScreen   ExtNewScreen
  26. #endif
  27. #include "Amiga:wbstruct.h"
  28. #include "Amiga:wbprotos.h"
  29.  
  30. #ifdef CLI
  31. #include "Amiga:wbdata.c"       /* All structures and global data */
  32.  
  33. #undef NetHackCnf
  34. char NetHackCnf[50]="NetHack:NetHack.cnf";
  35. #endif  /* CLI */
  36.  
  37. #define C_GREY  0
  38. #define C_BLACK 1
  39. #define C_WHITE 2
  40. #define C_BLUE  3
  41.  
  42. #ifndef __SASC_60
  43. extern char *sys_errlist[];
  44. #endif
  45. extern int errno;
  46.  
  47. #define SPLIT           /* use splitter, if available */
  48.  
  49. void diskobj_filter(struct DiskObject *);
  50. BPTR s_LoadSeg(char *);
  51. void s_UnLoadSeg(void);
  52.  
  53. #ifdef CLI
  54. char *cnfsavedir="NetHack:save";    /* unless overridden in cnf file */
  55. char argline[255];  /* no overflow - bigger than ADOS will pass */
  56. #ifdef for_later
  57. int amibbs=0;                /* BBS mode flag */
  58. #endif
  59.  
  60. void WaitEOG(GPTR);
  61. char *eos(char *);
  62. void condaddslash(char *);
  63.  
  64. # ifdef SPLIT
  65. int running_split=0;        /* if 0, using normal LoadSeg/UnLoadSeg */
  66. # endif
  67. #else
  68. extern char *options[NUMIDX+1];
  69. extern GPTR gamehead,gameavail;
  70. extern struct Window *win;
  71. #endif  /* CLI */
  72.  
  73. #ifdef AZTEC_C
  74. extern char *strdup(char *);
  75.  
  76. /*
  77.  * Aztec has a strnicmp, but it doesn't work properly.
  78.  *
  79.  * Note: this came out of NHS:hacklib.c
  80.  */
  81. static char
  82. lowc(c)         /* force 'c' into lowercase */
  83.     char c;
  84. {
  85.     return ('A' <= c && c <= 'Z') ? (c | 040) : c;
  86. }
  87.  
  88. int
  89. strnicmp(s1, s2, n)
  90.     register const char *s1, *s2;
  91.     register int n;
  92. {
  93.     register char t1, t2;
  94.  
  95.     while (n--) {
  96.     if (!*s2) return (*s1 != 0);    /* s1 >= s2 */
  97.     else if (!*s1) return -1;   /* s1  < s2 */
  98.     t1 = lowc(*s1++);
  99.     t2 = lowc(*s2++);
  100.     if (t1 != t2) return (t1 > t2) ? 1 : -1;
  101.     }
  102.     return 0;               /* s1 == s2 */
  103. }
  104. #endif
  105.  
  106. #ifndef max
  107. # define max(a, b) ((a) > (b) ? (a) : (b))
  108. #endif
  109. #ifndef min
  110. # define min(x,y) ((x) < (y) ? (x) : (y))
  111. #endif
  112.  
  113. char *copyright_text[]={
  114. "NetHack, Copyright 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993.",
  115. "         By Stichting Mathematisch Centrum and M. Stephenson.",
  116. "         See license for details.",
  117. 0
  118. };
  119.  
  120. #ifdef CLI
  121.  
  122. main( argc, wbs )
  123.     int argc;
  124.     struct WBStartup *wbs;
  125. {
  126.     GPTR gptr;
  127.     BPTR lc,lc2;
  128.     struct FileInfoBlock finfo;
  129.     char *name=0;
  130.     char namebuf[50];
  131.     char **argv=(char **)wbs;
  132.     char newcmdline[80]="";
  133.     char forcenewcmd=0;
  134.  
  135.     ZapOptions( curopts );
  136.     InitWB( argc, (struct WBStartup *)argv );
  137.     errmsg( NO_FLASH, "Welcome to NetHack Version %d.%d.%d!\n",
  138.       VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL );
  139.     CopyRight( );
  140.  
  141.     ReadConfig( );
  142.  
  143. #ifdef for_later
  144.     /* check for BBS mode */
  145.     if (argc>1 && argv[1][0]==':'){
  146.     amibbs=1;
  147.     strcpy(newcmdline,":");
  148.     amibasename= &argv[1][1];
  149.     }
  150. #endif
  151.  
  152.         /* check/re-assemble initial command line */
  153.     {
  154.     int c;
  155.                 /* slow but easy - not a critical path */
  156.     for(c=1;c<argc;c++){
  157.     if(strlen(newcmdline)+strlen(argv[c])>=sizeof(newcmdline)){
  158.         forcenewcmd=1;
  159.         break;
  160.     }
  161.     strcpy(eos(newcmdline),argv[c]);
  162.     if(!strncmp(argv[c],"-u",2)){
  163.         if(!strcmp(argv[c],"-u")){
  164.         name= argv[c+1];
  165.         }else{
  166.         name= &argv[c][2];
  167.         }
  168.         if(!name){
  169.         errmsg(NO_FLASH, "No name found.\n");
  170.         newcmdline[0]='\0';    /* don't leave -u as default */
  171.         forcenewcmd=1;
  172.         }
  173.     }
  174.     if(c<argc)strcpy(eos(newcmdline)," ");
  175.     }
  176.     eos(newcmdline)[-1]='\0';
  177.     strcpy(argline,newcmdline);
  178.     }
  179.  
  180.     /* Wait till user quits */
  181.     while( !quit )
  182.     {
  183.     char tbuf[80];
  184.     char *p=tbuf;
  185.     char *dirname=cnfsavedir;
  186. /* play a game */
  187.  
  188.     if(forcenewcmd)
  189.         goto build_new_argline;    /* allow initial args to be wrong */
  190. #undef TESTCMDLINE
  191. #ifdef TESTCMDLINE
  192. __builtin_printf("sending '%s'\n",argline);
  193. #else
  194.     strcpy(namebuf,cnfsavedir);
  195.     condaddslash(namebuf);
  196.     if(!name)name="NewGame.info";
  197.     strcpy(eos(namebuf),name);
  198.     lc=Lock(namebuf,ACCESS_READ);
  199.     if(!lc){
  200.         dirname="NetHack:";
  201.         strcpy(namebuf,dirname);
  202.         strcpy(eos(namebuf),"NewGame.info");
  203.         lc=Lock(namebuf,ACCESS_READ);
  204.         if(!lc){
  205.         errmsg(NO_FLASH,"Can't find NewGame.info");
  206.         cleanup(1);
  207.         }
  208.     }
  209.     if(!Examine(lc,&finfo)){
  210.         errmsg(NO_FLASH,"Can't find info file.\n");
  211.         cleanup(1);
  212.     }
  213.     lc2=ParentDir(lc);
  214.     UnLock(lc);
  215.     gptr=GetWBIcon(lc2,dirname,&finfo);
  216.     if(!gptr)cleanup(1);
  217.     UnLock(lc2);
  218.     run_game(gptr);
  219.  
  220. /* wait for game to end */
  221.     if(gptr->wbs)
  222.         WaitEOG(gptr);
  223.     /* else load failed */
  224.  
  225.     FreeGITEM(gptr);
  226. #endif /* TESTCMDLINE */
  227. /* ask about another? */
  228. build_new_argline:
  229.     forcenewcmd=0;
  230. #ifdef for_later
  231.     if(amibbs) {
  232.         quit = 1;        /* bbs mode aborts after one game */
  233.     } else
  234. #endif
  235.     {
  236.     char *x=argline;
  237.     while(isspace(*x))x++;
  238.     if(*x){            /* non-blank argline */
  239.         printf("%s %s %s",
  240.           "Enter options for next game.  Default:\n\t", argline,
  241.           "\n(space return to clear) or Q to quit:\n");
  242.     } else {
  243.         printf("Enter options for next game or Q to quit:\n");
  244.     }
  245.     fgets(tbuf,sizeof(tbuf),stdin);
  246.     tbuf[strlen(tbuf)-1]='\0';        /* kill \n */
  247.     if(strlen(tbuf)==1 && (*p=='q' || *p=='Q')){
  248.         quit=1;
  249.         } else
  250.         if(strlen(tbuf))strcpy(argline,tbuf);
  251.     }
  252.     }
  253.     cleanup(0);
  254. }
  255.  
  256. /* CLI */
  257.  
  258. void
  259. WaitEOG(target)
  260.     GPTR target;
  261. {
  262.     long mask, rmask;
  263.     struct WBStartup *wbs;
  264.     struct WBArg *wba;
  265.     int i;
  266.     /* Get a message */
  267.     while(1){
  268.     mask = ( 1L << dosport->mp_SigBit ) ;
  269.     rmask = Wait( mask );
  270.  
  271.  
  272.     if( rmask & ( 1L << dosport->mp_SigBit ) )
  273.     {
  274.         /* Get process termination messages */
  275.  
  276.         while( wbs = (struct WBStartup *) GetMsg( dosport ) )
  277.         {
  278.         /* Find the game that has terminated */
  279.  
  280.         if(target->seglist == wbs->sm_Segment)
  281.         {
  282. #ifdef SPLIT
  283.             if(!running_split)
  284. #endif
  285.             /* Unload the code */
  286.             UnLoadSeg( wbs->sm_Segment );
  287.             /* Free the startup message resources */
  288.  
  289.             wba = (struct WBArg *)
  290.             ((long)wbs + sizeof( struct WBStartup ));
  291.             for( i = 0; i < wbs->sm_NumArgs; ++i )
  292.             {
  293.             FreeMem( wba[i].wa_Name, strlen( wba[i].wa_Name ) + 1 );
  294.             UnLock( wba[i].wa_Lock );
  295.             }
  296.             FreeMem( wbs, wbs->sm_Message.mn_Length );
  297.             wbs = NULL;
  298.  
  299.             return;
  300.         }
  301.         }
  302.  
  303.     }
  304.     }
  305. }
  306.  
  307. /* CLI */
  308.  
  309. void CopyRight()
  310. {
  311.     int line;
  312.     for(line=0;copyright_text[line];line++){
  313.     printf("%s\n",copyright_text[line]);
  314.     }
  315. }
  316.  
  317. /* CLI */
  318.  
  319. /*
  320.  * Do the one time initialization things.
  321.  */
  322.  
  323. void
  324. InitWB( argc, wbs )
  325.     int argc;
  326.     register struct WBStartup *wbs;
  327. {
  328.     char **argv=(char **)wbs;
  329.  
  330.     /* Open Libraries */
  331.     GfxBase= (struct GfxBase *) OldOpenLibrary("graphics.library");
  332.     IconBase= OldOpenLibrary("icon.library");
  333.     DiskfontBase= (struct DiskfontBase *)OldOpenLibrary("diskfont.library");
  334.     IntuitionBase= (struct IntuitionBase *)OldOpenLibrary("intuition.library");
  335.  
  336.     if(!GfxBase || !IconBase || !DiskfontBase || !IntuitionBase)
  337.     {
  338.     error("library open failed");
  339.     cleanup( 1 );
  340.     }
  341.  
  342.     /* Get Port for replied WBStartup messages */
  343.  
  344.     if( ( dosport = CreatePort( NULL, 0 ) ) == NULL )
  345.     {
  346.     error("failed to create dosport" );
  347.     cleanup( 1 );
  348.     }
  349.  
  350.     /* If started from CLI */
  351.     if( argc == 0 ){
  352.     printf("Run this program from CLI only.\n");
  353.     DisplayBeep(0);     /* could be more specific */
  354.     Delay(400);
  355.     cleanup(1);
  356.     }
  357. /* we should include hack.h but due to conflicting options to sc
  358.  * we can't parse tradstdc.h and clib/graphics_protos.h - fake it
  359.  */
  360. #define NEWS
  361. #define WIZARD
  362.     if (argc>1 && argv[1][0]=='?'){
  363.         (void) printf(
  364. "\nUsage:\n %s [:uname] [-d dir] -s [-[%s]] [maxrank] [name]...",
  365.         argv[0], classes);
  366.         (void) printf("\n or");
  367.         (void) printf("\n %s [-d dir] [-u name] [-[%s]]",
  368.         argv[0], classes);
  369. #if defined(WIZARD) || defined(EXPLORE_MODE)
  370.         (void) printf(" [-[DX]]");
  371. #endif
  372. #ifdef NEWS
  373.         (void) printf(" [-n]");
  374. #endif
  375. #ifndef AMIGA
  376.         (void) printf(" [-I] [-i] [-d]");
  377. #endif
  378. #ifdef MFLOPPY
  379. # ifndef AMIGA
  380.         (void) printf(" [-r]");
  381. # endif
  382. #endif
  383. #ifdef AMIGA
  384.         (void) printf(" [-[lL]]");
  385. #endif
  386.         putchar('\n');
  387.         cleanup(1);
  388.     }
  389. }
  390.  
  391. /* CLI */
  392.  
  393. /*
  394.  * Read a nethack.cnf like file and collect the configuration
  395.  * information from it.
  396.  */
  397. void ReadConfig()
  398. {
  399.     register FILE *fp;
  400.     register char *buf, *t;
  401.  
  402.     /* Use a dynamic buffer to limit stack use */
  403.  
  404.     if( ( buf = xmalloc( 1024 ) ) == NULL )
  405.     {
  406.     error( "Can't alloc space to read config file" );
  407.     cleanup( 1 );
  408.     }
  409.  
  410.     /* If the file is not there, can't load it */
  411.  
  412.     if( ( fp = fopen( NetHackCnf, "r" ) ) == NULL )
  413.     {
  414.     errmsg( FLASH, "Can't load config file %s", NetHackCnf );
  415.     free( buf );
  416.     return;
  417.     }
  418.  
  419.     /* Read the lines... */
  420.  
  421.     while( fgets( buf, 1024, fp ) != NULL )
  422.     {
  423.     if( *buf == '#' )
  424.         continue;
  425.  
  426.     if( ( t = strchr( buf, '\n' ) ) != NULL )
  427.         *t = 0;
  428.  
  429.     if( strnicmp( buf, "SAVE=", 5 ) == 0 )
  430.     {
  431.         cnfsavedir=strdup(buf+5);
  432.     }
  433.     else
  434.     {
  435.         /* We don't care about the rest */
  436.     }
  437.     }
  438.     fclose( fp );
  439.     free( buf );
  440. }
  441.  
  442. /* CLI */
  443.  
  444. void
  445. run_game( gptr )
  446.     register GPTR gptr;
  447. {
  448.     struct Task *ctask;
  449.     register struct MsgPort *proc = NULL;
  450.     int tidx;
  451.  
  452.     tidx = 0;
  453.  
  454.     gptr->gname = xmalloc( 20 + strlen( gptr->name ) );
  455.  
  456.     SetToolLine(gptr, "INTERNALCLI", argline);
  457.     gptr->wbs = AllocMem( sizeof( struct WBStartup ) +
  458.     ( sizeof( struct WBArg ) * 2 ), MEMF_PUBLIC | MEMF_CLEAR );
  459.  
  460.     /* Check if we got everything */
  461.  
  462.     if( !gptr->gname || !gptr->wbs )
  463.     {
  464.     fprintf( stderr, "Can't allocate memory\n" );
  465.     goto freemem;
  466.     }
  467.  
  468.     /* Get the arguments structure space */
  469.  
  470.     gptr->wba = ( struct WBArg * ) ((long)gptr->wbs + 
  471.     sizeof( struct WBStartup ) );
  472.     /* Load the game into memory */
  473. #ifdef SPLIT
  474.     /* Which version do we run? */
  475.     {
  476.     char gi[80];
  477.     BPTR tmplock;
  478.  
  479.     sprintf( gi, "%s.dir", GAMEIMAGE );
  480.     tmplock=Lock( gi, ACCESS_READ );
  481.     if( tmplock ){
  482.     UnLock( tmplock );
  483.     gptr->seglist = (BPTR)s_LoadSeg( gi );
  484.     if(gptr->seglist)running_split=1;
  485.     }else{
  486.     gptr->seglist = (BPTR)LoadSeg( GAMEIMAGE );
  487.     }
  488.     }
  489. #else
  490.     gptr->seglist = (BPTR)LoadSeg( GAMEIMAGE );
  491. #endif
  492.  
  493.     if( gptr->seglist == NULL)
  494.     {
  495.     errmsg( FLASH, "Can't load %s", GAMEIMAGE );
  496.     goto freemem;
  497.     }
  498.  
  499.     /* Set the game name for the status command */
  500.     sprintf( gptr->gname, "NetHack %d.%d.%d %s",
  501.       VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, gptr->name );
  502.  
  503.     /* Create a process for the game to execute in */
  504.     ctask = FindTask( NULL );
  505.     proc = CreateProc( gptr->gname, ctask->tc_Node.ln_Pri,
  506.             gptr->seglist, GAMESTACK );
  507.  
  508.     /* Check if the create failed */
  509.  
  510.     if( proc == NULL )
  511.     {
  512.     fprintf(stderr, "Error creating process %d\n", IoErr() );
  513. #ifdef SPLIT
  514.     if(!running_split)
  515. #endif
  516.         UnLoadSeg( gptr->seglist );
  517. freemem:
  518.     if( gptr->gname ) free( gptr->gname );
  519.     gptr->gname = NULL;
  520.  
  521.     if( gptr->wbs ) FreeMem( gptr->wbs,
  522.         sizeof( struct WBStartup ) + sizeof( struct WBArg ) * 2 );
  523.     gptr->wbs = NULL;
  524.     return;
  525.     }
  526.  
  527.     /* Get the Process structure pointer */
  528.     gptr->prc = (struct Process *) (((long)proc) - sizeof( struct Task ));
  529.  
  530.     /* Set the current directory */
  531.     gptr->prc->pr_CurrentDir=((struct Process *)FindTask(NULL))->pr_CurrentDir;
  532.  
  533.     /* Fill in the startup message */
  534.     gptr->wbs->sm_Process = proc;
  535.     gptr->wbs->sm_Segment = gptr->seglist;
  536.     gptr->wbs->sm_NumArgs = 2;
  537.     {
  538.     static char title[45];    /* some slack */
  539.     sprintf(title,"con:0/0/100/300/NetHack %d.%d.%d",
  540.       VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
  541.     gptr->wbs->sm_ToolWindow = title;
  542.     }
  543.     gptr->wbs->sm_ArgList = gptr->wba;
  544.  
  545.     /* Fill in the args */
  546.  
  547.     gptr->wba[0].wa_Name = Strdup( GAMEIMAGE );
  548.     gptr->wba[0].wa_Lock = Lock( dirname( GAMEIMAGE ), ACCESS_READ );
  549.  
  550.     gptr->wba[1].wa_Name = Strdup( gptr->name );
  551.     gptr->wba[1].wa_Lock = Lock( gptr->dname, ACCESS_READ );
  552.  
  553.     /* Write the updated tools types entries */
  554.  
  555.     WriteDObj( gptr, gptr->wba[1].wa_Lock );
  556.  
  557.     /* Set the message fields correctly */
  558.  
  559.     gptr->wbs->sm_Message.mn_Node.ln_Type = NT_MESSAGE;
  560.     gptr->wbs->sm_Message.mn_Node.ln_Pri = 0;
  561.     gptr->wbs->sm_Message.mn_ReplyPort = dosport;
  562.     gptr->wbs->sm_Message.mn_Length =
  563.     sizeof( struct WBStartup ) + ( sizeof( struct WBArg ) * 2 );
  564.  
  565.     /* Send the WB Startup message to let the game go... */
  566.  
  567.     PutMsg( proc, &gptr->wbs->sm_Message );
  568. }
  569.  
  570. #else   /* CLI */
  571.  
  572. void RPText( rp, s )
  573.     struct RastPort *rp;
  574.     register char *s;
  575. {
  576.     Text( rp, s, strlen( s ) );
  577. }
  578.  
  579. /* !CLI */
  580.  
  581. void
  582. SetUpMenus( mp, scrn )
  583.     register struct Menu *mp;
  584.     register struct Screen *scrn;
  585. {
  586.     register struct MenuItem *mip;
  587.     register int i, leftoff = 0, horiz=0, len;
  588.     register int com, chk;
  589.  
  590.     for( ; mp; mp = mp->NextMenu )
  591.     {
  592.     i = 0;
  593.     horiz = (scrn->RastPort.TxWidth*strlen(mp->MenuName))+16;
  594.     /*mp->LeftEdge = leftoff;*/
  595.     com = chk = 0;
  596.     for( mip = mp->FirstItem; mip; mip = mip->NextItem )
  597.     {
  598.         if( mip->Flags & COMMSEQ )
  599.         com = scrn->RastPort.TxWidth * 6;
  600.         if( mip->Flags & CHECKIT )
  601.         chk = scrn->RastPort.TxWidth * 3;
  602.     }
  603.     for( mip = mp->FirstItem; mip; mip = mip->NextItem )
  604.     {
  605.         mip->Height = scrn->RastPort.TxHeight;
  606.         mip->TopEdge = scrn->RastPort.TxHeight * i++;
  607.  
  608.         len = IntuiTextLength((struct IntuiText *)
  609.             (mip->ItemFill))+8+com+chk;
  610.         horiz = max( horiz,len );
  611.     }
  612.  
  613.     for( mip = mp->FirstItem; mip; mip = mip->NextItem )
  614.     {
  615.         mip->Width = horiz;
  616.     }
  617.     leftoff += horiz;
  618.     }
  619. }
  620.  
  621. /* !CLI */
  622.  
  623. /* Get a text line from the indicated file based on an array of per
  624.  * line offsets.
  625.  */
  626.  
  627. void getline( fp, offarr, which, buf, size )
  628.     FILE *fp;
  629.     long *offarr;
  630.     int which, size;
  631.     char *buf;
  632. {
  633.     fseek( fp, offarr[ which ], 0 );
  634.     fgets( buf, size, fp );
  635. }
  636.  
  637. /* !CLI */
  638.  
  639. void
  640. do_closewindow()
  641. {
  642.     /*set close flag - cleanup must be done elsewhere*/
  643.     cleanup( 0 );
  644. }
  645.  
  646. /* !CLI */
  647.  
  648. void
  649. menu_copyopt()
  650. {
  651.     GPTR gptr;
  652.     char newname[ 100 ], oldname[ 100 ], cmd[ 300 ], dir[ 100 ];
  653.  
  654.     if( ( gptr = NeedGame() ) == NULL )
  655.     return;
  656.  
  657.     if( StrRequest( "Enter new player name", newname, gptr->name ) == 0 )
  658.     return;
  659.  
  660.     if( strcmp( newname, gptr->name ) == 0 )
  661.     {
  662.     errmsg( FLASH, "Copying aborted, new name same as old" );
  663.     return;
  664.     }
  665.  
  666.     strcpy( oldname, GameName( gptr, NULL ) );
  667.  
  668.     strcpy( dir, options[ SAVE_IDX ] );
  669.     if( strchr( "/:", dir[strlen(dir)-1] ) == 0 && *dir )
  670.     strcat( dir, "/" );
  671.     if( gptr->dobj->do_Gadget.GadgetID == GADNEWGAME )
  672.     sprintf( cmd, "c:copy \"%s\" \"%s%s.cfg.info\"", oldname, dir, newname );
  673.     else
  674.     sprintf( cmd, "c:copy \"%s\" \"%s%s.info\"", oldname, dir, newname );
  675.     Execute( cmd, NULL, NULL );
  676.     MapGadgets( R_DISK, 1 );
  677. }
  678.  
  679. /* !CLI */
  680.  
  681. void
  682. menu_rename()
  683. {
  684.     register GPTR gptr;
  685.     char newname[ 100 ], oldname[ 100 ], cmd[ 200 ], name[100], *t;
  686.  
  687.     if( ( gptr = NeedGame() ) == NULL )
  688.     return;
  689.  
  690.     strcpy( newname, gptr->name );
  691.     if( t = strrchr( newname, '.' ) )
  692.     {
  693.     if( strcmp( t, ".sav" ) == 0 )
  694.         *t = 0;
  695.     }
  696.  
  697.     if( StrRequest( "Enter New Name For Game", name, newname ) == 0)
  698.     return;
  699.  
  700.     /* Name can only be this long to allow inclusion of appropriate suffix */
  701.     name[ 30 - strlen( ".sav.info " ) ] = '\0';
  702.  
  703.     if( strcmp( name, newname ) == 0 )
  704.     {
  705.     errmsg( FLASH, "Rename aborted, name unchanged from %s", newname );
  706.     return;
  707.     }
  708.  
  709.     strcat( name, ".sav" );
  710.  
  711.     strcpy( oldname, GameName( gptr, NULL ) );
  712.  
  713.     strcpy( newname, GameName( gptr, name ) );
  714.     strcat( newname, ".info" );
  715.  
  716.     /* Rename icon file */
  717.     sprintf( cmd, "c:rename \"%s\" \"%s\"", oldname, newname );
  718.     Execute( cmd, NULL, NULL );
  719.  
  720.     strcpy( oldname, GameName( gptr, gptr->name ) );
  721.  
  722.     strcpy( newname, GameName( gptr, name ) );
  723.  
  724.     /* Rename save file if it is actually there */
  725.     if( access( oldname, 0 ) == 0 )
  726.     {
  727.     sprintf( cmd, "c:rename \"%s\" \"%s\"", oldname, newname );
  728.     Execute( cmd, NULL, NULL );
  729.     }
  730.  
  731.     MapGadgets( R_DISK, 1 );
  732. }
  733.  
  734. #endif  /* CLI */
  735.  
  736. void CleanUpLists( )
  737. {
  738.     register GPTR gptr;
  739.  
  740.     while( gptr = gamehead )
  741.     {
  742.     gamehead = gamehead->next;
  743.     FreeGITEM( gptr );
  744.     }
  745.  
  746.     while( gptr = gameavail )
  747.     {
  748.     gameavail = gameavail->next;
  749.     free( gptr );
  750.     }
  751. }
  752.  
  753. #ifndef CLI
  754.  
  755. void SafeCloseWindow( window )
  756.     register struct Window *window;
  757. {
  758.     register struct Message *msg;
  759.  
  760.     if( !window )
  761.     return;
  762.  
  763.     /* Remove any attached menu */
  764.  
  765.     if( window->MenuStrip )
  766.     {
  767.     ClearMenuStrip( window );
  768.     }
  769.  
  770.     Forbid();
  771.     while( window->UserPort != NULL &&
  772.         ( msg = GetMsg( window->UserPort) ) != NULL )
  773.     {
  774.     ReplyMsg( msg );
  775.     }
  776.  
  777.     CloseWindow( window );
  778.     Permit();
  779. }
  780.  
  781. void RemoveGITEM( ggptr )
  782.     register GPTR ggptr;
  783. {
  784.     register GPTR gptr, pgptr = NULL;
  785.  
  786.     for( gptr = gamehead; gptr; pgptr = gptr, gptr = gptr->next )
  787.     {
  788.     if( gptr == ggptr )
  789.     {
  790.         if( pgptr )
  791.         pgptr->next = gptr->next;
  792.         else
  793.         gamehead = gptr->next;
  794.         FreeGITEM( gptr );
  795.         return;
  796.     }
  797.     }
  798. }
  799.  
  800.  
  801. #else   /* CLI */
  802.  
  803. void CloseLibraries( )
  804. {
  805.     if( IntuitionBase )     CloseLibrary( (void *) IntuitionBase );
  806.     IntuitionBase = 0;
  807.     if( DiskfontBase )      CloseLibrary( (void *) DiskfontBase );
  808.     DiskfontBase = 0;
  809.     if( IconBase )          CloseLibrary(  IconBase );
  810.     IconBase = 0;
  811.     if( GfxBase )           CloseLibrary( (void *) GfxBase );
  812.     GfxBase = 0;
  813. }
  814.  
  815. /* CLI */
  816.  
  817. void cleanup( code )
  818.     int code;
  819. {
  820.     if( dosport ) DeletePort( dosport );
  821.     dosport = NULL;
  822.  
  823.     CleanUpLists( );
  824.     CloseLibraries( );
  825.  
  826. #ifdef SPLIT
  827.     if(running_split){
  828.     s_UnLoadSeg();
  829.     }
  830. #endif
  831.     exit( code );
  832. }
  833.  
  834. /* CLI */
  835.  
  836. GPTR AllocGITEM( )
  837. {
  838.     register GPTR gptr;
  839.  
  840.     if( gameavail )
  841.     {
  842.     gptr = gameavail;
  843.     gameavail = gameavail->next;
  844.     }
  845.     else
  846.     {
  847.     gptr = xmalloc( sizeof( GAMEITEM ) );
  848.     }
  849.  
  850.     if( gptr )
  851.     memset( gptr, 0, sizeof( GAMEITEM ) );
  852.  
  853.     return( gptr );
  854. }
  855.  
  856. /* CLI */
  857.  
  858. void FreeGITEM( gptr )
  859.     register GPTR gptr;
  860. {
  861.     /* Free all of the pieces first */
  862.  
  863.     if( gptr->talloc )
  864.     FreeTools( gptr );
  865.  
  866.     if( gptr->dobj )
  867.     FreeDObj( gptr->dobj );
  868.  
  869.     gptr->dobj = NULL;
  870.  
  871.     if( gptr->name )
  872.     free( gptr->name );
  873.     gptr->name = NULL;
  874.  
  875.     if( gptr->dname )
  876.     free( gptr->dname );
  877.     gptr->dname = NULL;
  878.  
  879.     if( gptr->fname )
  880.     free( gptr->fname );
  881.     gptr->fname = NULL;
  882.  
  883.     /* Connect it to free list */
  884.  
  885.     gptr->next = gameavail;
  886.     gameavail = gptr;
  887. }
  888.  
  889. /* CLI */
  890.  
  891. struct DiskObject *AllocDObj( str )
  892.     register char *str;
  893. {
  894.     register struct DiskObject *doptr;
  895.     register char *t, *t1;
  896.  
  897.     if( ( t = strrchr( str, '.' ) ) && stricmp( t, ".info" ) == 0 )
  898.     {
  899.     *t = 0;
  900.     } else {
  901.     t = NULL;
  902.     }
  903.  
  904.     if( doptr = GetDiskObject( str ) )
  905.     {
  906.     struct IntuiText *ip;
  907.  
  908.     diskobj_filter(doptr);  /* delete all but INTERNALCLI */
  909.  
  910.     if( ip = xmalloc( sizeof( struct IntuiText ) ) )
  911.     {
  912.         memset( ip, 0, sizeof( struct IntuiText ) );
  913.         ip->FrontPen = C_BLACK;
  914.         ip->DrawMode = JAM1;
  915.         ip->IText = strdup( str );
  916.         doptr->do_Gadget.GadgetText = ip;
  917.  
  918.         /* Trim any .sav off of the end. */
  919.  
  920.         if( ( t1 = strrchr( ip->IText, '.' ) ) &&
  921.         stricmp( t1, ".sav" ) == 0 )
  922.         {
  923.         *t1 = 0;
  924.         ip->LeftEdge = (2 * win->RPort->TxWidth);
  925.         }
  926.         }
  927.     }
  928.     if( t ) *t = '.';
  929.  
  930.     return( doptr );
  931. }
  932.  
  933. #endif  /* CLI */
  934.  
  935. void FreeDObj( doptr )
  936.     register struct DiskObject *doptr;
  937. {
  938.     if( doptr->do_Gadget.GadgetText )
  939.     {
  940.     free( doptr->do_Gadget.GadgetText->IText );
  941.     free( doptr->do_Gadget.GadgetText );
  942.     }
  943.     doptr->do_Gadget.GadgetText = NULL;
  944.     FreeDiskObject( doptr );
  945. }
  946.  
  947. #ifdef CLI
  948. #ifdef AZTEC_C
  949. void errmsg(int flash, char *str, ...)
  950. #else
  951. void errmsg( flash, str )
  952. char *str;
  953. int flash;
  954. #endif
  955. {
  956.     va_list vp;
  957.  
  958.     va_start( vp, str );
  959.  
  960. /*  if( !win || !wbopen ) */
  961.     {
  962.     vprintf( str, vp );
  963.     va_end( vp );
  964.     printf("\n");
  965.     return;
  966.     }
  967.  
  968. }
  969.  
  970. /* CLI */
  971.  
  972. /*
  973.  * Issue an error message to the users window because it can not be done
  974.  * any other way.
  975.  */
  976.  
  977. void error( str )
  978.     register char *str;
  979. {
  980.     char s[ 50 ];
  981.     if( scrn ) ScreenToBack( scrn );
  982.     Delay( 10 );
  983.     fprintf( stderr, "%s\n", str );
  984.     fprintf( stderr, "Hit Return: " );
  985.     fflush( stderr );
  986.     gets( s );
  987.     if( scrn ) ScreenToFront( scrn );
  988. }
  989.  
  990. #else   /* CLI */
  991.  
  992. void menu_scores()
  993. {
  994.     register char buf1[50];
  995.     register char **oldtools;
  996.     register GPTR gptr;
  997.     int oldalloc;
  998.     extern GPTR windowgads;
  999.  
  1000.     if( StrRequest( "Scores for whom?", buf1, "all" ) != 0 )
  1001.     {
  1002.     for( gptr = windowgads; gptr; gptr = gptr->nextwgad )
  1003.     {
  1004.         if( gptr->dobj->do_Gadget.GadgetID == GADNEWGAME )
  1005.         break;
  1006.     }
  1007.  
  1008.     if( !gptr )
  1009.     {
  1010.         errmsg( FLASH, "Can't find NewGame icon" );
  1011.         return;
  1012.     }
  1013.  
  1014.     /* Save current tools */
  1015.     oldtools = gptr->dobj->do_ToolTypes;
  1016.  
  1017.     /* Force a new tooltypes array to be allocated */
  1018.     if( oldalloc = gptr->talloc )
  1019.     {
  1020.         gptr->dobj->do_ToolTypes = gptr->otools;
  1021.         gptr->talloc = 0;
  1022.     }
  1023.  
  1024.     /* Add the scores entry */
  1025.     SetToolLine( gptr, "SCORES", *buf1 ? buf1 : "all" );
  1026.  
  1027.     /* Get the scores */
  1028.     run_game( gptr );
  1029.  
  1030.     /* Free the tools which contain "SCORES=" */
  1031.     FreeTools( gptr );
  1032.  
  1033.     /* Restore the old tools.  When this game exits, the tools
  1034.      * will be written back out to disk to update things
  1035.      */
  1036.     gptr->dobj->do_ToolTypes = oldtools;
  1037.     gptr->talloc = oldalloc;
  1038.     Delay( 100 );
  1039.     UpdateGameIcon( gptr );
  1040.     }
  1041. }
  1042.  
  1043. /* !CLI */
  1044.  
  1045. CheckAndCopy( gadstr, origstr )
  1046.     char *gadstr, *origstr;
  1047. {
  1048.     char *t;
  1049.     int i;
  1050.  
  1051.     if( t = strchr( gadstr, '=' ) )
  1052.     {
  1053.     i = t - gadstr;
  1054.     /* Check for original string and don't allow one line to be replaced with
  1055.      * another.
  1056.      */
  1057.     if( *origstr != 0 && strncmp( gadstr, origstr, i ) != 0 )
  1058.     {
  1059.         strcpy( gadstr, origstr );
  1060.         DisplayBeep( NULL );
  1061.         return( 0 );
  1062.     }
  1063.     }
  1064.     else
  1065.     {
  1066.     /* If added an equals, there wasn't one previously, so signal an error */
  1067.     if( t = strchr( origstr, '=' ) )
  1068.     {
  1069.         strcpy( gadstr, origstr );
  1070.         DisplayBeep( NULL );
  1071.         return( 0 );
  1072.     }
  1073.     }
  1074.     return( 1 );
  1075. }
  1076.  
  1077. /* !CLI */
  1078.  
  1079. int IsEditEntry( str, gptr )
  1080.     char *str;
  1081.     register GPTR gptr;
  1082. {
  1083.     if( strncmp( str, "CHARACTER=", 10 ) == 0 )
  1084.     return( 0 );
  1085.     return( 1 );
  1086. }
  1087.  
  1088. /* !CLI */
  1089.  
  1090. void menu_comment( )
  1091. {
  1092.     register GPTR gptr;
  1093.     struct FileInfoBlock *finfo;
  1094.     BPTR lock;
  1095.     char commentstr[ 100 ];
  1096.  
  1097.     if( ( gptr = NeedGame() ) == NULL )
  1098.     return;
  1099.  
  1100.     if( ( lock = Lock( GameName( gptr, NULL ), ACCESS_READ ) ) == NULL )
  1101.     {
  1102.     /* Can't get lock, reload and return */
  1103.  
  1104.     errmsg( FLASH, "Can't Lock game save file: %s",
  1105.             GameName( gptr, NULL ) );
  1106.     MapGadgets( R_DISK, 1 );
  1107.     return;
  1108.     }
  1109.  
  1110.     finfo = (struct FileInfoBlock *) xmalloc(sizeof(struct FileInfoBlock));
  1111.     Examine( lock, finfo );
  1112.     UnLock( lock );
  1113.     strncpy( commentstr, finfo->fib_Comment, sizeof( finfo->fib_Comment ) );
  1114.     commentstr[ sizeof( finfo->fib_Comment ) ] = 0;
  1115.     free( finfo );
  1116.  
  1117.     /* Set the correct size */
  1118.     if( StrRequest( "Edit Comment as Desired",
  1119.         commentstr, commentstr ) == 0 )
  1120.     {
  1121.     return;
  1122.     }
  1123.  
  1124.     SetComment( GameName( gptr, NULL ), commentstr );
  1125. }
  1126.  
  1127. /* !CLI */
  1128.  
  1129. /*
  1130.  * Make the proportional gadget position match the values passed
  1131.  */
  1132.  
  1133. void UpdatePropGad( win, gad, vis, total, top )
  1134.     struct Window *win;
  1135.     struct Gadget *gad;
  1136.     register long vis, total, top;
  1137. {
  1138.     register long hidden;
  1139.     register int body, pot;
  1140.  
  1141.     hidden = max( total-vis, 0 );
  1142.  
  1143.     if( top > hidden )
  1144.     top = hidden;
  1145.  
  1146.     if( hidden > 0 )
  1147.     body = (ULONG) (vis * MAXBODY) / total;
  1148.     else
  1149.     body = MAXBODY;
  1150.  
  1151.     if( hidden > 0 )
  1152.     pot = (top * MAXPOT) / hidden;
  1153.     else
  1154.     pot = 0;
  1155.  
  1156.     NewModifyProp( gad, win, NULL,
  1157.         AUTOKNOB|FREEHORIZ, pot, 0, body, MAXBODY, 1 );
  1158. }
  1159.  
  1160. #endif  /* CLI */
  1161.  
  1162. /*
  1163.  * Allocate some memory
  1164.  */
  1165.  
  1166. void *xmalloc( nbytes )
  1167.     unsigned nbytes;
  1168. {
  1169.     return( malloc( nbytes ) );
  1170. }
  1171.  
  1172. #ifndef CLI
  1173. /*
  1174.  * Delete the game associated with the GAME structure passed
  1175.  */
  1176.  
  1177. int DeleteGame( gptr )
  1178.     register GPTR gptr;
  1179. {
  1180.     register int err;
  1181.  
  1182.     err = DeleteFile( GameName( gptr, gptr->name ) );
  1183.     err += DeleteFile( GameName( gptr, NULL ) );
  1184.     return( err );
  1185. }
  1186. #endif  /* CLI */
  1187.  
  1188. /*
  1189.  * Look through the list of games for one named 'name'
  1190.  */
  1191.  
  1192. GPTR FindGame( name )
  1193.     char *name;
  1194. {
  1195.     register GPTR gptr;
  1196.  
  1197.     for( gptr = gamehead; gptr; gptr = gptr->next )
  1198.     {
  1199.     if( stricmp( gptr->fname, name ) == 0 )
  1200.         break;
  1201.     }
  1202.  
  1203.     return( gptr );
  1204. }
  1205. /*
  1206.  * Set the option string indicated by idx to 'str'
  1207.  */
  1208.  
  1209. void setoneopt( idx, str )
  1210.     int idx;
  1211.     char *str;
  1212. {
  1213.     /* This space accumulates, but is recovered at process exit */
  1214.  
  1215.     options[ idx ] = strdup( str );
  1216. }
  1217.  
  1218. /*
  1219.  * Get just the directory name of str
  1220.  */
  1221.  
  1222. char *dirname( str )
  1223.     char *str;
  1224. {
  1225.     static char buf[ 300 ];
  1226.     char *t;
  1227.  
  1228.     strncpy( buf, str, sizeof( buf ) );
  1229.     buf[ sizeof( buf ) - 1 ] = 0;
  1230.  
  1231.     if( (t = strrchr( buf, '/' ) ) == NULL ||
  1232.         (t = strrchr( buf, ':' ) ) == NULL )
  1233.     {
  1234.     return( "/" );
  1235.     }
  1236.     *t = 0;
  1237.     return( buf );
  1238. }
  1239.  
  1240. #ifndef CLI
  1241.  
  1242. /*
  1243.  * Make sure that only itemno is checked in 'menu' off of menuptr
  1244.  */
  1245.  
  1246. void CheckOnly( menuptr, menu, itemno )
  1247.     register struct Menu *menuptr;
  1248.     register int menu, itemno;
  1249. {
  1250.     register struct MenuItem *ip;
  1251.  
  1252.     while( menuptr && menu-- )
  1253.     menuptr = menuptr->NextMenu;
  1254.  
  1255.     if( menuptr )
  1256.     {
  1257.     for( ip = menuptr->FirstItem; ip && itemno; itemno--)
  1258.     {
  1259.         ip->Flags &= ~CHECKED;
  1260.         ip = ip->NextItem;
  1261.     }
  1262.  
  1263.     if( ip )
  1264.     {
  1265.         ip->Flags |= CHECKED;
  1266.         ip = ip->NextItem;
  1267.     }
  1268.  
  1269.     while( ip )
  1270.     {
  1271.         ip->Flags &= ~CHECKED;
  1272.         ip = ip->NextItem;
  1273.     }
  1274.     }
  1275. }
  1276.  
  1277. /* !CLI */
  1278.  
  1279. int FindChecked( menuptr, menu )
  1280.     register struct Menu *menuptr;
  1281.     register int menu;
  1282. {
  1283.     register int itemno;
  1284.     register struct MenuItem *ip;
  1285.  
  1286.     while( menuptr && menu-- )
  1287.     menuptr = menuptr->NextMenu;
  1288.  
  1289.     if( menuptr )
  1290.     {
  1291.     for( itemno = 0, ip = menuptr->FirstItem; ip; ip = ip->NextItem )
  1292.     {
  1293.         if( ip->Flags & CHECKED )
  1294.         return( itemno );
  1295.         ++itemno;
  1296.     }
  1297.     }
  1298.     return( 0 );
  1299. }
  1300.  
  1301. /* !CLI */
  1302.  
  1303. /*
  1304.  * Create a file name based in the GAMEs directory.  If file is NULL,
  1305.  * the file name is the icon file.  Otherwise it is 'file'.
  1306.  */
  1307.  
  1308. char *GameName( gptr, file )
  1309.     GPTR gptr;
  1310.     char *file;
  1311. {
  1312.     static char buf[200];
  1313.  
  1314.     if( file == NULL )
  1315.     file = gptr->fname;
  1316.  
  1317.     if( strchr( "/:", gptr->dname[ strlen( gptr->dname ) - 1 ] ) )
  1318.     sprintf( buf, "%s%s", gptr->dname, file );
  1319.     else
  1320.     sprintf( buf, "%s/%s", gptr->dname, file );
  1321.     return( buf );
  1322. }
  1323.  
  1324. #endif  /* CLI */
  1325.  
  1326. /*
  1327.  * Allocate a new GAME structure for the file passed and fill it in
  1328.  */
  1329.  
  1330. GPTR GetWBIcon( lock, dir, finfo )
  1331.     register BPTR lock;
  1332.     register char *dir;
  1333.     register struct FileInfoBlock *finfo;
  1334. {
  1335.     register BPTR odir;
  1336.     register char *t;
  1337.     register GPTR gptr;
  1338.  
  1339.     if( ( gptr = AllocGITEM( ) ) == NULL )
  1340.     goto noitems;
  1341.  
  1342.     if( ( gptr->dname = strdup( dir ) ) == NULL )
  1343.     goto outofmem;
  1344.  
  1345.     if( ( gptr->fname = strdup( finfo->fib_FileName ) ) == NULL )
  1346.     goto outofmem;
  1347.  
  1348.     /* Strip the .info off. */
  1349.     if( t = strrchr( finfo->fib_FileName, '.' ) )
  1350.     {
  1351.     if( stricmp( t, ".info" ) == 0 )
  1352.         *t = 0;
  1353.     else
  1354.         t = NULL;
  1355.     }
  1356.  
  1357.     if( ( gptr->name = strdup( finfo->fib_FileName ) ) == NULL )
  1358.     goto outofmem;
  1359.  
  1360.     /* If removed .info, put it back */
  1361.  
  1362.     if( t )
  1363.     *t = '.';
  1364.  
  1365.     /* Change to saved game directory */
  1366.  
  1367.     odir = CurrentDir( lock );
  1368.  
  1369.     /* Allocate a diskobj structure */
  1370.  
  1371.     if( ( gptr->dobj = AllocDObj( finfo->fib_FileName ) ) == NULL )
  1372.     {
  1373.     (void) CurrentDir( odir );
  1374. outofmem:
  1375.     FreeGITEM( gptr );
  1376.  
  1377.     if( gptr->fname )
  1378.         free( gptr->fname );
  1379.     gptr->fname = NULL;
  1380.  
  1381.     if( gptr->name )
  1382.         free( gptr->name );
  1383.     gptr->name = NULL;
  1384.  
  1385.     if( gptr->dname )
  1386.         free( gptr->dname );
  1387.     gptr->dname = NULL;
  1388.  
  1389. noitems:
  1390.     errmsg( FLASH, "Can't get Disk Object: %s", finfo->fib_FileName );
  1391.     return( NULL );
  1392.     }
  1393.     gptr->oflag = gptr->dobj->do_Gadget.Flags;
  1394.     gptr->oact = gptr->dobj->do_Gadget.Activation;
  1395.     gptr->dobj->do_Gadget.Activation |=
  1396.         ( RELVERIFY | GADGIMMEDIATE | FOLLOWMOUSE );
  1397.     gptr->dobj->do_Gadget.Flags &= ~(GADGHIGHBITS);
  1398.     gptr->dobj->do_Gadget.Flags |= GADGHNONE;
  1399.  
  1400.     /* Make sure gptr->dobj->do_ToolTypes is not NULL */
  1401.     ReallocTools( gptr, 0 );
  1402.  
  1403.     (void) CurrentDir( odir );
  1404.     return( gptr );
  1405. }
  1406.  
  1407. #ifndef CLI
  1408.  
  1409. /*
  1410.  * Put a 3-D motif border around the gadget.  String gadgets or those
  1411.  * which do not have highlighting are rendered down.  Boolean gadgets
  1412.  * are rendered in the up position by default.
  1413.  */
  1414.  
  1415. void SetBorder( gd, val )
  1416.     register struct Gadget *gd;
  1417.     int val;
  1418. {
  1419.     register struct Border *bp;
  1420.     register short *sp;
  1421.     register int i;
  1422.     int borders = 6;
  1423.  
  1424.     /* Allocate two border structures one for up image and one for down
  1425.      * image, plus vector arrays for the border lines.
  1426.      */
  1427.  
  1428.     if( gd->GadgetType == STRGADGET )
  1429.     borders = 12;
  1430.  
  1431.     if( ( bp = xmalloc( ( ( sizeof( struct Border ) * 2 ) +
  1432.         ( sizeof( short ) * borders ) ) * 2 ) ) == NULL )
  1433.     {
  1434.     return;
  1435.     }
  1436.  
  1437.     /* Remove any special rendering flags to avoid confusing intuition
  1438.      */
  1439.  
  1440.     gd->Flags &= ~(GADGHIGHBITS|GADGIMAGE|GRELWIDTH|
  1441.             GRELHEIGHT|GRELRIGHT|GRELBOTTOM);
  1442.  
  1443.     sp = (short *)(bp + 4);
  1444.     if( val == 0 || val == 2 ||
  1445.     gd->GadgetType == STRGADGET || ( gd->GadgetType == BOOLGADGET &&
  1446.         ( gd->Flags & GADGHIGHBITS ) == GADGHNONE ) )
  1447.     {
  1448.     /* For a string gadget, we expand the border beyond the area where
  1449.      * the text will be entered.
  1450.      */
  1451.  
  1452.     sp[0] = -1;
  1453.     sp[1] = gd->Height - 1;
  1454.     sp[2] = -1;
  1455.     sp[3] = -1;
  1456.     sp[4] = gd->Width-1;
  1457.     sp[5] = -1;
  1458.  
  1459.     sp[6] = gd->Width + 1;
  1460.     sp[7] = -2;
  1461.     sp[8] = gd->Width + 1;
  1462.     sp[9] = gd->Height + 1;
  1463.     sp[10] = -2;
  1464.     sp[11] = gd->Height + 1;
  1465.  
  1466.     sp[12] = -2;
  1467.     sp[13] = gd->Height;
  1468.     sp[14] = -2;
  1469.     sp[15] = -2;
  1470.     sp[16] = gd->Width;
  1471.     sp[17] = -2;
  1472.     sp[18] = gd->Width;
  1473.     sp[19] = gd->Height;
  1474.     sp[20] = -2;
  1475.     sp[21] = gd->Height;
  1476.  
  1477.     for( i = 0; i < 3; ++i )
  1478.     {
  1479.         bp[ i ].LeftEdge = bp[ i ].TopEdge = -1;
  1480.         if( val == 2 )
  1481.         bp[ i ].FrontPen = ( i == 0 || i == 1 ) ? C_WHITE : C_BLACK;
  1482.         else
  1483.         bp[ i ].FrontPen = ( i == 0 || i == 1 ) ? C_BLACK : C_WHITE;
  1484.  
  1485.         /* Have to use JAM2 so that the old colors disappear. */
  1486.         bp[ i ].BackPen = C_GREY;
  1487.         bp[ i ].DrawMode = JAM2;
  1488.         bp[ i ].Count = ( i == 0 || i == 1 ) ? 3 : 5;
  1489.         bp[ i ].XY = &sp[ i*6 ];
  1490.         bp[ i ].NextBorder = ( i == 2 ) ? NULL : &bp[ i + 1 ];
  1491.     }
  1492.  
  1493.     /* Set the up image */
  1494.     gd->GadgetRender = (APTR) bp;
  1495.  
  1496.     /* Same image for select image */
  1497.     gd->SelectRender = (APTR) bp;
  1498.  
  1499.     gd->LeftEdge++;
  1500.     gd->TopEdge++;
  1501.     gd->Flags |= GADGHCOMP;
  1502.     }
  1503.     else
  1504.     {
  1505.     /* Create the border vector values for up and left side, and
  1506.      * also the lower and right side.
  1507.      */
  1508.  
  1509.     sp[0] = 0;
  1510.     sp[1] = gd->Height;
  1511.     sp[2] = 0;
  1512.     sp[3] = 0;
  1513.     sp[4] = gd->Width;
  1514.     sp[5] = 0;
  1515.  
  1516.     sp[6] = gd->Width;
  1517.     sp[7] = 0;
  1518.     sp[8] = gd->Width;
  1519.     sp[9] = gd->Height;
  1520.     sp[10] = 0;
  1521.     sp[11] = gd->Height;
  1522.  
  1523.     /* We are creating 4 sets of borders, the two sides of the
  1524.      * rectangle share the border vectors with the opposite image,
  1525.      * but specify different colors.
  1526.      */
  1527.  
  1528.     for( i = 0; i < 4; ++i )
  1529.     {
  1530.         bp[ i ].TopEdge = bp[ i ].LeftEdge = 0;
  1531.  
  1532.         /* A GADGHNONE is always down */
  1533.  
  1534.         if( val != 3 && gd->GadgetType == BOOLGADGET &&
  1535.         ( gd->Flags & GADGHIGHBITS ) != GADGHNONE )
  1536.         {
  1537.         bp[ i ].FrontPen =
  1538.             ( i == 1 || i == 2 ) ? C_BLACK : C_WHITE;
  1539.         }
  1540.         else
  1541.         {
  1542.         bp[ i ].FrontPen =
  1543.             ( i == 1 || i == 3 ) ? C_WHITE : C_BLACK;
  1544.         }
  1545.  
  1546.         /* Have to use JAM2 so that the old colors disappear. */
  1547.         bp[ i ].BackPen = C_GREY;
  1548.         bp[ i ].DrawMode = JAM2;
  1549.         bp[ i ].Count = 3;
  1550.         bp[ i ].XY = &sp[ 6 * ((i &1) != 0) ];
  1551.         bp[ i ].NextBorder =
  1552.         ( i == 1 || i == 3 ) ? NULL : &bp[ i + 1 ];
  1553.     }
  1554.  
  1555.     /* bp[0] and bp[1] two pieces for the up image */
  1556.     gd->GadgetRender = (APTR) bp;
  1557.  
  1558.     /* bp[2] and bp[3] two pieces for the down image */
  1559.     gd->SelectRender = (APTR) (bp + 2);
  1560.     gd->Flags |= GADGHIMAGE;
  1561.     }
  1562. }
  1563.  
  1564. /* !CLI */
  1565.  
  1566. struct Gadget *FindGadget( window, newwindow, id )
  1567.     struct Window *window;
  1568.     struct NewWindow *newwindow;
  1569.     int id;
  1570. {
  1571.     struct Gadget *gd = NULL;
  1572.  
  1573.     if( window )
  1574.     gd = window->FirstGadget;
  1575.     else if( newwindow )
  1576.     gd = newwindow->FirstGadget;
  1577.  
  1578.     while( gd )
  1579.     {
  1580.     if( gd->GadgetID == id )
  1581.         break;
  1582.     gd = gd->NextGadget;
  1583.     }
  1584.  
  1585.     return( gd );
  1586. }
  1587.  
  1588. #endif  /* CLI */
  1589.  
  1590. /*
  1591.  * Clear all previous values from passed options array
  1592.  */
  1593. void ZapOptions( optr )
  1594.     OPTR optr;
  1595. {
  1596.     int i;
  1597.  
  1598.     for( i = 0; optr[ i ].name; ++i )
  1599.     {
  1600.     if( optr[i].optstr )
  1601.     {
  1602.         if( *optr[i].optstr )
  1603.         {
  1604.         free( optr[i].optstr );
  1605.         optr[i].optstr = "";
  1606.         }
  1607.     }
  1608.     else
  1609.     {
  1610.         optr[i].optval = optr[i].defval;
  1611.     }
  1612.     }
  1613. }
  1614.  
  1615. #ifndef CLI
  1616.  
  1617. /*
  1618.  * Copy Options from GAMES OPTIONS= tooltypes element to the gadgets
  1619.  */
  1620. void CopyOptions( optr, gptr )
  1621.     OPTR optr;
  1622.     GPTR gptr;
  1623. {
  1624.     char *sp;
  1625.  
  1626.     sp = ToolsEntry( gptr, "OPTIONS" );
  1627.     ZapOptions( optr );
  1628.     if( sp && *sp )
  1629.     CopyOptionStr( optr, sp );
  1630. }
  1631.  
  1632. /* !CLI */
  1633.  
  1634. void CopyOptionStr( optr, str )
  1635.     OPTR optr;
  1636.     char *str;
  1637. {
  1638.     char *s, *t, buf[ 100 ];
  1639.     int i, sidx, state = 0;
  1640.     int done = 0;
  1641.  
  1642.     ZapOptions( optr );
  1643.     s = buf;
  1644.     *buf = 0;
  1645.     sidx = -1;
  1646.  
  1647.     /* Start past the 'options=' part */
  1648.     for( t = str; *str && !done; ++t )
  1649.     {
  1650.     if( state == 0 && isspace( *t ) )
  1651.         continue;
  1652.  
  1653.     /* If at end remember so... */
  1654.     if( !*t )
  1655.         done = 1;
  1656.  
  1657.     /* If looking for an option value */
  1658.     if( state == 0 )
  1659.     {
  1660.         /* If found string value... */
  1661.         if( *t == ':' )
  1662.         {
  1663.         *s = 0;
  1664.         state = 1;
  1665.         sidx = -1;
  1666.  
  1667.         /* Look for the particular named option */
  1668.         for( i = 0; optr[i].name; ++i )
  1669.         {
  1670.             if( stricmp( optr[i].name, buf ) == 0 )
  1671.             {
  1672.             sidx = i;
  1673.             break;
  1674.             }
  1675.         }
  1676.  
  1677.         /* Set buffer pointer */
  1678.         *(s = buf) = 0;
  1679.  
  1680.         if( sidx == -1 )
  1681.         {
  1682.             errmsg( FLASH, "Invalid option name %s", buf );
  1683.             return;
  1684.         }
  1685.         if( !optr[i].optstr )
  1686.         {
  1687.             errmsg( FLASH, "%s is not a string option", buf );
  1688.             return;
  1689.         }
  1690.         continue;
  1691.         }
  1692.     }
  1693.  
  1694.     /* If at end of string or comma and we have some text... */
  1695.     if( ( !*t || *t == ',' ) && *buf )
  1696.     {
  1697.         /* Mark end */
  1698.         *s = 0;
  1699.  
  1700.         /* If have collected string option value... */
  1701.         if( sidx != -1 )
  1702.         {
  1703.         /* Free old string */
  1704.         if( optr[sidx].optstr )
  1705.         {
  1706.             if( *optr[sidx].optstr )
  1707.             free( optr[sidx].optstr );
  1708.         }
  1709.  
  1710.         /* Store new string */
  1711.         if( *buf )
  1712.             optr[sidx].optstr = strdup( buf );
  1713.         else
  1714.             optr[sidx].optstr = "";
  1715.         sidx = -1;
  1716.         }
  1717.         else
  1718.         {
  1719.         /* Look for boolean option */
  1720.         for( i = 0; optr[i].name; ++i )
  1721.         {
  1722.             if( *buf == '!' )
  1723.             {
  1724.             if( stricmp( optr[i].name, buf + 1 ) == 0 )
  1725.                 break;
  1726.             }
  1727.             else
  1728.             {
  1729.             if( stricmp( optr[i].name, buf ) == 0 )
  1730.                 break;
  1731.             }
  1732.         }
  1733.  
  1734.         if( optr[i].name )
  1735.         {
  1736.             optr[i].optval = *buf != '!';
  1737.         }
  1738.         else
  1739.         {
  1740.             errmsg( FLASH, "Unrecognized option `%s'", buf );
  1741.             return;
  1742.         }
  1743.         }
  1744.         *(s = buf) = 0;
  1745.         state = 0;
  1746.     }
  1747.     else
  1748.     {
  1749.         if( *t == ',' )
  1750.         *(s = buf) = 0;
  1751.         else
  1752.         *s++ = *t;
  1753.     }
  1754.     }
  1755. }
  1756.  
  1757. /* !CLI */
  1758.  
  1759. /*
  1760.  *  Set the GAMES OPTIONS tooltypes to the data in the Options windows
  1761.  *  gadgetry.
  1762.  */
  1763. void SetOptions( optr, gptr )
  1764.     register OPTR optr;
  1765.     register GPTR gptr;
  1766. {
  1767.     PutOptions( optr );
  1768.     SetToolLine( gptr, "OPTIONS", options[ OPTIONS_IDX ] );
  1769. }
  1770.  
  1771. void
  1772. UpdateGameIcon( gptr )
  1773.     register GPTR gptr;
  1774. {
  1775.     register long lock;
  1776.  
  1777.     if( lock = Lock( gptr->dname, ACCESS_READ ) )
  1778.     {
  1779.     /* Write out the DiskObject */
  1780.  
  1781.     WriteDObj( gptr, lock );
  1782.     UnLock( lock );
  1783.     }
  1784.     else
  1785.     {
  1786.     errmsg( FLASH, "Can't change directory to %s", gptr->dname );
  1787.     }
  1788. }
  1789.  
  1790. #endif  /* CLI */
  1791.  
  1792. char *ToolsEntry( gptr, name )
  1793.     GPTR gptr;
  1794.     char *name;
  1795. {
  1796.     char *str;
  1797.  
  1798.     if( ! ( str = FindToolType( (char **) gptr->dobj->do_ToolTypes, name ) ) )
  1799.     str = "";
  1800.  
  1801.     return( str );
  1802. }
  1803.  
  1804. /* Reallocate the toolstype information into dynamic memory so that some
  1805.  * parts of it can be easily changed, but we can still do "FreeDiskObject"
  1806.  * later to clean up whatever "GetDiskObject" allocated.
  1807.  */
  1808. void ReallocTools( gptr, add )
  1809.     register GPTR gptr;
  1810.     register int add;
  1811. {
  1812.     register int i, cnt;
  1813.     register char **sp, **tp;
  1814.  
  1815.     /* Already allocated */
  1816.     if( gptr->talloc && add == 0 )
  1817.         return;
  1818.  
  1819.     for( cnt = 0, tp = gptr->dobj->do_ToolTypes; tp && *tp ; ++tp )
  1820.     ++cnt;
  1821.  
  1822.     if( !tp || cnt == 0 )
  1823.     {
  1824.     if( gptr->talloc )
  1825.         free( gptr->dobj->do_ToolTypes );
  1826.     /* If no tooltypes array, fudge something to start with */
  1827.     if( sp = xmalloc( 2 * sizeof( char * ) ) )
  1828.     {
  1829.         sp[0] = strdup("HACKDIR=NetHack:");
  1830.         sp[1] = NULL;
  1831.     }
  1832.     }
  1833.     else if( sp = xmalloc( (cnt+1+add) * sizeof( char * ) ) )
  1834.     {
  1835.     for( i = 0, tp = gptr->dobj->do_ToolTypes;
  1836.             tp && *tp && i < cnt; ++tp )
  1837.     {
  1838.         sp[i++] = strdup( *tp );
  1839.     }
  1840.  
  1841.     if( gptr->talloc && gptr->dobj->do_ToolTypes )
  1842.         free( gptr->dobj->do_ToolTypes );
  1843.     while( i < cnt+add+1 )
  1844.         sp[ i++ ] = NULL;
  1845.     }
  1846.     if( ! gptr->talloc )
  1847.     gptr->otools = gptr->dobj->do_ToolTypes;
  1848.     gptr->dobj->do_ToolTypes = sp;
  1849.     gptr->toolcnt = cnt + 1;
  1850.     gptr->talloc = 1;
  1851. }
  1852.  
  1853. void FreeTools( gptr )
  1854.     register GPTR gptr;
  1855. {
  1856.     register int i;
  1857.     register char **sp;
  1858.  
  1859.     if( !gptr->talloc )
  1860.     return;
  1861.  
  1862.     for( i = 0, sp = gptr->dobj->do_ToolTypes; sp[i]; ++i )
  1863.     {
  1864.     free( sp[ i ] );
  1865.     sp[ i ] = NULL;
  1866.     }
  1867.     free( sp );
  1868.     gptr->dobj->do_ToolTypes = gptr->otools;
  1869.     gptr->talloc = 0;
  1870. }
  1871.  
  1872. void SetToolLine( gptr, name, value )
  1873.     GPTR gptr;
  1874.     char *name, *value;
  1875. {
  1876.     char **sp, **osp;
  1877.     int i, len;
  1878.  
  1879.     /* Realloc ToolTypes to be in memory we know how to manage */
  1880.  
  1881.     ReallocTools( gptr, 0 );
  1882.  
  1883.     sp = gptr->dobj->do_ToolTypes;
  1884.     len = strlen( name );
  1885.  
  1886.     /* Find any previous definition */
  1887.     for( i = 0; sp[i] && i < gptr->toolcnt - 1; ++i )
  1888.     {
  1889.     if( strnicmp( name, sp[i], len ) == 0 && sp[i][len] == '=' )
  1890.         break;
  1891.     }
  1892.  
  1893.     /* Free up the space, or allocate new space if not there */
  1894.     if( sp[ i ] )
  1895.     free( sp[ i ] );
  1896.     else
  1897.     {
  1898.     /* Check for need to realloc */
  1899.  
  1900.     if( i >= gptr->toolcnt - 1 )
  1901.     {
  1902.         int j=i;
  1903.         osp = sp;
  1904.         sp = xmalloc( ( i + 2 ) * sizeof( char * ) );
  1905.         gptr->toolcnt = i + 2;
  1906.         sp[ i + 1 ] = NULL;
  1907.         while( j >= 0 )
  1908.         {
  1909.         sp[ j ] = osp[ j ];
  1910.         --j;
  1911.         }
  1912.         free( osp );
  1913.         /* i = gptr->toolcnt - 1; */
  1914.         gptr->dobj->do_ToolTypes = sp;
  1915.     }
  1916.     else
  1917.     {
  1918.         sp[ i + 1 ] = NULL;
  1919.     }
  1920.     }
  1921.  
  1922.     /* Set the string */
  1923.  
  1924.     if( sp[ i ] = xmalloc( strlen (value) + strlen( name ) + 2 ) )
  1925.     sprintf( sp[i], "%s=%s", name, value );
  1926.     else
  1927.     {
  1928.     sp[ i ] = NULL;     /* redundant */
  1929.     errmsg( FLASH, "Could not allocate string for value" );
  1930.     }
  1931. }
  1932.  
  1933. void WriteDObj( gptr, lock )
  1934.     register GPTR gptr;
  1935.     long lock;
  1936. {
  1937.     register long odir;
  1938.     long flag, act;
  1939.  
  1940.     /* Don't write gadget out as selected */
  1941.  
  1942.     flag = gptr->dobj->do_Gadget.Flags;
  1943.     act = gptr->dobj->do_Gadget.Activation;
  1944.     gptr->dobj->do_Gadget.Flags = gptr->oflag;
  1945.     gptr->dobj->do_Gadget.Activation = gptr->oact;
  1946.     odir = CurrentDir( lock );
  1947.  
  1948.     if( PutDiskObject( gptr->name, gptr->dobj ) == 0 )
  1949.     errmsg( FLASH, "Could not write disk object values" );
  1950.  
  1951.     gptr->dobj->do_Gadget.Flags = flag;
  1952.     gptr->dobj->do_Gadget.Activation = act;
  1953.  
  1954.     if( odir )
  1955.     (void) CurrentDir( odir );
  1956. }
  1957.  
  1958. char *Strdup( str )
  1959.     char *str;
  1960. {
  1961.     char *t;
  1962.  
  1963.     if( t = AllocMem( strlen( str ) + 1, MEMF_PUBLIC ) )
  1964.     strcpy( t, str );
  1965.     return( t );
  1966. }
  1967.  
  1968. #ifdef CLI
  1969.  
  1970. char *
  1971. eos(s)
  1972.     char *s;
  1973. {
  1974.     while(*s)s++;
  1975.     return s;
  1976. }
  1977.  
  1978. /* CLI */
  1979.  
  1980. void
  1981. condaddslash(s)
  1982.     char *s;
  1983. {
  1984.     s=eos(s);
  1985.     switch(s[-1]){
  1986.     case ':':
  1987.     case '/':
  1988.     break;
  1989.     default:
  1990.     s[0]='/';
  1991.     s[1]='\0';
  1992.     break;
  1993.     }
  1994.     return;
  1995. }
  1996.  
  1997. /* CLI */
  1998.  
  1999. #if 0
  2000. /* for debug only */
  2001. #define BP __builtin_printf
  2002. dumptools(sp,i)
  2003.     char **sp;
  2004.     int i;
  2005. {
  2006.     int x;
  2007.     BP("Dumptools: cnt=%d\n",i);
  2008.     for(x=0;sp[x];x++)
  2009.     BP("%d: '%s'\n",x,sp[x]);
  2010. }
  2011. #endif
  2012.  
  2013. #else   /* CLI */
  2014.  
  2015. void ClearDelGames()
  2016. {
  2017.     register GPTR gptr, pgptr = NULL;
  2018.  
  2019.     for( gptr = gamehead; gptr; )
  2020.     {
  2021.     /* Skip New Game */
  2022.  
  2023.     if( gptr->fname == NULL )
  2024.     {
  2025.         gptr = gptr->next;
  2026.         continue;
  2027.     }
  2028.  
  2029.     /* If gone, then remove structures */
  2030.  
  2031.     if( access( GameName( gptr, NULL ), 0 ) == -1 )
  2032.     {
  2033.         if( pgptr )
  2034.         pgptr->next = gptr->next;
  2035.         else
  2036.         gamehead = gptr->next;
  2037.  
  2038.         FreeGITEM( gptr );
  2039.         gptr = pgptr ? pgptr : gamehead;
  2040.     }
  2041.     else
  2042.     {
  2043.         pgptr = gptr;
  2044.         gptr = gptr->next;
  2045.     }
  2046.     }
  2047. }
  2048.  
  2049. /* !CLI */
  2050.  
  2051. struct TagItem tags[] =
  2052. {
  2053.     TAG_DONE, 0l,
  2054. };
  2055.  
  2056. struct Window *
  2057. MyOpenWindow( nw )
  2058. #ifdef  INTUI_NEW_LOOK
  2059.     struct ExtNewWindow *nw;
  2060. #else
  2061.     struct NewWindow *nw;
  2062. #endif
  2063. {
  2064. #ifdef  INTUI_NEW_LOOK
  2065.     /*nw->Extension = tags;
  2066.     nw->Flags = WFLG_NW_EXTENDED;*/
  2067. #endif
  2068. #undef  NewWindow
  2069.     return( OpenWindow( (struct NewWindow *) nw ) );
  2070. }
  2071.  
  2072. #endif  /* CLI */
  2073.  
  2074. void
  2075. diskobj_filter( dobj )
  2076.     struct DiskObject *dobj;
  2077. {
  2078.     char **ta=dobj->do_ToolTypes;
  2079.     int x;
  2080.  
  2081.     /* if nothing there, just return. */
  2082.     if( !ta )
  2083.         return;
  2084.  
  2085. #ifdef CLI
  2086.     /* kill everything except INTERNALCLI */
  2087.  
  2088.     for(x=0;ta[x];x++){
  2089.     if(!strncmp(ta[x],"INTERNALCLI=",12)){
  2090.         ta[0]=ta[x];
  2091.         ta[1]=0;
  2092.         return;
  2093.     }
  2094.     }
  2095.     ta[0]=0;
  2096. #else
  2097.     /* kill INTERNALCLI */
  2098.     for(x=0;ta[x];x++){
  2099.         int offset=0;
  2100.     while(ta[x+offset] && !strncmp(ta[x+offset],"INTERNALCLI=",12)){
  2101.         offset++;
  2102.         }
  2103.         ta[x]=ta[x+offset];
  2104.     }
  2105. #endif
  2106. }
  2107.